#include "Thread.hpp"
#include "Mutex.hpp"



// int tickets = 1000;
// pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

// void* buyTicket(void* args)
// {
//     char* username = (char*)args;
//     while (true)
//     {
//         pthread_mutex_lock(&lock);
//         if (tickets <= 0)
//         {
//             pthread_mutex_unlock(&lock);
//             break;
//         }
//         usleep(12345);//让线程频繁切换
//         cout << username << "正在抢票" << tickets << endl;
//         tickets--;
//         pthread_mutex_unlock(&lock);
//     }
//     return nullptr;
// }

// int main()
// {
//     unique_ptr<Thread> t1(new Thread(buyTicket, (void*)"user1", 1));
//     unique_ptr<Thread> t2(new Thread(buyTicket, (void*)"user2", 2));
//     unique_ptr<Thread> t3(new Thread(buyTicket, (void*)"user3", 3));
//     unique_ptr<Thread> t4(new Thread(buyTicket, (void*)"user4", 4));
//     t1->join();
//     t2->join();
//     t3->join();
//     t4->join();
//     return 0;
//}


//全局锁 局部锁
#define NUM 4

int tickets = 10000;

//pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;//全局锁 无需init和destroy

struct ThreadData
{
    string _name;
    pthread_mutex_t* _lock;
};

void* buyTicket(void* args)
{
    ThreadData* t = (ThreadData*)args;
    while (true)
    {
        {
            lockGuard lockguard(t->_lock);//构造加锁 析构解锁
            if (tickets <= 0)
                break;//出作用域 lockguard自动调用析构解锁
            usleep(1234);//让多线程之间频繁切换造成共享资源访问冲突
            cout << t->_name << "正在抢票" << tickets << endl;
            tickets--;
        }//加作用域是为了不影响usleep 否则解锁后当前线程仍然会去抢占资源
        usleep(1234);//释放锁后 留出时间让其他线程能抢到锁
    }
    delete t;
    return nullptr;
}

int main()
{
    pthread_mutex_t lock;//局部锁 需要init和destroy
    pthread_mutex_init(&lock, nullptr);
    vector<pthread_t> threads(NUM);
    for (int i = 0; i < NUM; i++)
    {
        pthread_t tid;
        ThreadData* t = new ThreadData;
        char name[64];
        snprintf(name, sizeof name, "user%d", i + 1);
        t->_name = name;//赋值重载
        t->_lock = &lock;
        pthread_create(&tid, nullptr, buyTicket, (void*)t);
        threads[i] = tid;
    }
    for (auto& tid : threads)
    {
        pthread_join(tid, nullptr);
    }
    pthread_mutex_destroy(&lock);
    return 0;
}
